using OhioState.Graphics;
using OhioState.Graphics.Proxy;
using Tao.OpenGl;

namespace OhioState.Graphics.OpenGL
{
    public class BoxBoundaryGL : IDrawable
    {
        #region Public Properties
        private BoundingBox _bBox;
        public IBoundingVolume BoundingVolume
        {
            get { return _bBox; }
            set
            {
                BoundingBox bBox = value as BoundingBox;
                if (bBox != null)
                {
                    _bBox = (BoundingBox)bBox.Clone();
                }
            }
        }
        private int _drawablePosition;
        public int DrawablePosition
        {
            get { return _drawablePosition; }
            set { _drawablePosition = value; }
        }
        private bool _drawBackFaces = true;
        public bool DrawBackFaces
        {
            get { return _drawBackFaces; }
            set { _drawBackFaces = value; }
        }
        private bool _drawFrontFaces = true;
        public bool DrawFrontFaces
        {
            get { return _drawFrontFaces; }
            set { _drawFrontFaces = value; }
        }
        private IMaterial _material;
        public IMaterial Material
        {
            get { return _material; }
            set { _material = value; }
        }
        #endregion Public Properties

        public BoxBoundaryGL(BoundingBox bBox)
        {
            _bBox = bBox;
        }
        public void Update(IRenderPanel panel)
        {
        }
        public void Render(IRenderPanel panel)
        {
            if (!_drawFrontFaces && !_drawBackFaces)
            {
                return;
            }
            bool culling = true;
            if (_drawBackFaces && _drawFrontFaces)
            {
                culling = false;
            }
            bool bFront = true;
            if (culling)
            {
                bFront = _drawFrontFaces;
            }

            Gl.glPushAttrib(Gl.GL_POLYGON_BIT | Gl.GL_CURRENT_BIT);
            if (culling)
            {
                Gl.glEnable(Gl.GL_CULL_FACE);
                Gl.glFrontFace(Gl.GL_CCW);
                Gl.glCullFace(bFront ? Gl.GL_BACK : Gl.GL_FRONT);
            }

            _material.MakeActive(panel);

            drawFaces();

            Gl.glPopAttrib();

            Gl.glDisable(Gl.GL_CULL_FACE);
            _material.Deactivate(panel);
        }
        private void drawFaces()
        {
            float x0, y0, z0, x1, y1, z1;
            x0 = _bBox.LowerLeft[0]; y0 = _bBox.LowerLeft[1]; z0 = _bBox.LowerLeft[2];
            x1 = _bBox.UpperRight[0]; y1 = _bBox.UpperRight[1]; z1 = _bBox.UpperRight[2];

            Gl.glBegin(Gl.GL_QUADS);
            // face 0
            Gl.glNormal3f(1, 0, 0);
            Gl.glVertex3f(x0, y0, z0); Gl.glVertex3f(x0, y0, z1); Gl.glVertex3f(x0, y1, z1); Gl.glVertex3f(x0, y1, z0);
            // face 1
            Gl.glNormal3f(-1, 0, 0);
            Gl.glVertex3f(x1, y0, z0); Gl.glVertex3f(x1, y1, z0); Gl.glVertex3f(x1, y1, z1); Gl.glVertex3f(x1, y0, z1);
            // face 2
            Gl.glNormal3f(0, 1, 0);
            Gl.glVertex3f(x0, y0, z0); Gl.glVertex3f(x1, y0, z0); Gl.glVertex3f(x1, y0, z1); Gl.glVertex3f(x0, y0, z1);
            // face 3
            Gl.glNormal3f(0, -1, 0);
            Gl.glVertex3f(x0, y1, z0); Gl.glVertex3f(x0, y1, z1); Gl.glVertex3f(x1, y1, z1); Gl.glVertex3f(x1, y1, z0);
            // face 4
            Gl.glNormal3f(0, 0, 1);
            Gl.glVertex3f(x0, y0, z0); Gl.glVertex3f(x0, y1, z0); Gl.glVertex3f(x1, y1, z0); Gl.glVertex3f(x1, y0, z0);
            // face 5
            Gl.glNormal3f(0, 0, -1);
            Gl.glVertex3f(x0, y0, z1); Gl.glVertex3f(x1, y0, z1); Gl.glVertex3f(x1, y1, z1); Gl.glVertex3f(x0, y1, z1);
            Gl.glEnd();
        }
    }
}
